﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Services;
using System.Web.UI.WebControls;
using Foothill.Common;
using Foothill.Common.Logging;
using Foothill.IoC;
using Foothill.Model;
using Foothill.Service;
using Foothill.Service.AdService;
using Foothill.Service.Caching;
using Foothill.Service.MiscInfo;
using Foothill.Service.Session;
using Foothill.Service.UploadPhoto;
using Foothill.Service.VehicleInfo;
using Foothill.Service.Validation;
using Foothill.Service.UserAccount;

namespace Foothill.Web
{
    public partial class PostForSalePreview : FoothillBasePage
    {
        private ISessionService _sessionService;
        private IVehicleInfoService _vehicleInfoService;
        private IMiscInfoService _miscInfoService;
        private IAdService _adService;
        private IUploadPhotoService _uploadPhotoService;
        private ILocalCache _localCache;
        private IPostValidator _validator;
        private IValidationService _validationService;  

        private string _EditButtonCaption = "编辑内容";

        protected void Page_Load(object sender, EventArgs e)
        {
            _sessionService = IocContainer.GetInstance<ISessionService>();
            _vehicleInfoService = IocContainer.GetInstance<IVehicleInfoService>();
            _miscInfoService = IocContainer.GetInstance<IMiscInfoService>();
            _adService = IocContainer.GetInstance<IAdService>();
            _localCache = IocContainer.GetInstance<ILocalCache>();
            _validator = IocContainer.GetInstance<IPostValidator>();
            _uploadPhotoService = IocContainer.GetInstance<IUploadPhotoService>();
            _validationService = IocContainer.GetInstance<IValidationService>();

            if (!IsPostBack)
            {
                InitPage(); 
                DisplayAdDetails();
            }

            DisplayPhotos();
        }

        [WebMethod]
        public static int DeleteUploadedPhoto(string filenameNoExt)
        {
            if (!string.IsNullOrWhiteSpace(filenameNoExt))
            {
                IList<UploadPhoto> uploadedPhotos = GetUploadedPhotoListFromSession();

                if (uploadedPhotos.Count == 1)
                {
                    // need to have at least 1 photo
                    return -1;
                }

                UploadPhoto fileToDelete = uploadedPhotos.FirstOrDefault(p => string.Compare(Path.GetFileNameWithoutExtension(p.PathOnServer), filenameNoExt, true) == 0);

                if (fileToDelete != null)
                {
                    IUploadPhotoService uploadPhotoService = IocContainer.GetInstance<IUploadPhotoService>();

                    try
                    {
                        // delete physical files - photo and thumbnail
                        uploadPhotoService.DeletePhotoAndThumbnail(fileToDelete.PathOnServer, fileToDelete.PathOnServer);
                    }
                    catch (Exception ex)
                    {
                        Log.Error(FoothillModule.View, "Fail to delete a photo from the disk", ex);
                    }

                    uploadedPhotos.Remove(fileToDelete);

                    ISessionService sessionService = IocContainer.GetInstance<ISessionService>();
                    sessionService.SaveSessionValue(SessionNames.ForSalePhotoList, uploadedPhotos);

                    return 0;
                }
            }

            return -1;
        }

        [WebMethod]
        public static void SaveEditPhotoChanges(List<string> list)
        {
            IList<UploadPhoto> photoList = GetUploadedPhotoListFromSession();

            foreach (UploadPhoto uploadPhoto in photoList)
            {
                int index = list.FindIndex(x => x.Equals(uploadPhoto.PathOnServer));
                uploadPhoto.DisplayIndex = index;
            }

            ISessionService sessionService = IocContainer.GetInstance<ISessionService>();
            sessionService.SaveSessionValue(SessionNames.ForSalePhotoList, photoList);
        }

        private void InitPage()
        {
            // initialize vehicle make/model list
            InitMakeList();

            // initialize year list
            InitYearList();

            // initialize city list
            InitCityList();
        }

        private void InitMakeList()
        {
            PopulateDropDownList(ddlMake, _vehicleInfoService.GetVehicleMakes());
        }

        private void InitYearList()
        {
            PopulateDropDownList( ddlYear, Utility.GetYearDict() );
        }

        private void InitCityList()
        {
            PopulateDropDownList(ddlCity, _miscInfoService.GetCities((int)Provinces.BC));
        }

        private void PopulateModelList( int makeId )
        {
            PopulateDropDownList(ddlModel, _vehicleInfoService.GetVehicleModels(makeId));
        }

        private void DisplayAdDetails()
        {
            PopulateDisplayControls();
            btnEditAdInfo.Text = _EditButtonCaption;
        }

        // display list of uploaded photos on the data list
        private void DisplayPhotos()
        {
            // get the list of photos from session
            IList<UploadPhoto> listOfPhotos = GetUploadedPhotoListFromSession();

            if (listOfPhotos != null)
            {
                // bind the list to the dataList
                dltPhotos.DataSource = listOfPhotos;
                dltPhotos.DataBind();

                // display profile image
                UploadPhoto profilePhoto = listOfPhotos.FirstOrDefault(p => p.DisplayIndex == 0);
                
                if (profilePhoto != null)
                {
                    imgProfile.ImageUrl = _uploadPhotoService.GetUploadPhotoImageUrl(profilePhoto.PathOnServer);          
                }
            }

            udpPhotos.Update();
        }

        // this handles display thumbnail image on the datalist
        protected void dltPhotos_OnItemCreated(object sender, DataListItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                UploadPhoto photo = e.Item.DataItem as UploadPhoto;

                if (photo != null)
                {
                    ImageButton btn = e.Item.FindControl("btnThumbnail") as ImageButton;

                    string path = _uploadPhotoService.GetThumbnailPhotoImageUrl(photo.PathOnServer);
                    btn.ImageUrl = path;       
                }
            }
        }

        protected void btnThumbnail_Click(object sender, EventArgs e)
        {
            DataListItem item = (DataListItem)((ImageButton)sender).NamingContainer;

            // datakey is photopath
            string photoPath = dltPhotos.DataKeys[item.ItemIndex].ToString();

            imgProfile.ImageUrl = _uploadPhotoService.GetUploadPhotoImageUrl(photoPath); 

            dltPhotos.DataSource = GetUploadedPhotoListFromSession();
            dltPhotos.DataBind();
        }
     
        protected void btnEditAdInfo_Click(object sender, EventArgs e)
        {
            PopulateEditControls();
            mpeEditPost.Show();
        }

        // get the photo list from the session, sorted by display index
        private static IList<UploadPhoto> GetUploadedPhotoListFromSession()
        {
            IList<UploadPhoto> retVal;
            ISessionService sessionService = IocContainer.GetInstance<ISessionService>();
            object obj = sessionService.GetSessionValue(SessionNames.ForSalePhotoList);

            if (obj == null)
            {
                // no photo has been uploaded yet
                retVal = new List<UploadPhoto>();
            }
            else
            {
                retVal = obj as List<UploadPhoto>;
            }

            return retVal.OrderBy(p => p.DisplayIndex).ToList();
        }

        private void PopulateEditControls()
        {
            ForSaleAd ad;
            object o = _sessionService.GetSessionValue(SessionNames.NewForSaleAd);

            if (o != null)
            {
                ad = o as ForSaleAd;

                txtPrice.Text = ad.PriceStr;
                ddlYear.SelectedValue = ad.YearMadeStr;
                ddlMake.SelectedValue = ad.MakeId.ToString();

                // populate the model list based on makeId
                PopulateModelList(ad.MakeId);

                ddlModel.SelectedValue = ad.ModelId.ToString();

                // transmission type
                RadioButton rbtToCheck = ad.TransmissionTypeId == (int)TransmissionType.Automatic ? rbtAutomatic : rbtStandard;
                rbtToCheck.Checked = true;

                // vehicle consition - used or new
                rbtToCheck = ad.VehicleConditionId == (int)VehicleCondition.New ? rbtNew : rbtUsed;
                rbtToCheck.Checked = true;

                // by owner or dealer
                rbtToCheck = ad.ListingTypeId == (int)ListingTypes.Owner? rbtOwner : rbtDealer;
                rbtToCheck.Checked = true;

                txtMileAgeValue.Text = ad.MileAgeStr;
                txtDescriptionDetail.Text = ad.Description;
                txtPhoneNumber.Text = ad.ContactPhone;
                txtEmail.Text = ad.ContactEmail;
                tbxContactName.Text = ad.ContactName;
                ddlCity.SelectedValue = ad.CityId.ToString();
            }
        }

        private void PopulateDisplayControls()
        {
            ForSaleAd ad;
            object obj = _sessionService.GetSessionValue(SessionNames.NewForSaleAd);

            if (obj != null)
            {
                ad = obj as ForSaleAd;

                lblPrice.Text = "$" + ad.PriceStr;
                lblConditionValue.Text = _localCache.GetStringValue(ApplicationDataNames.VehicleCondition, ad.VehicleConditionId);

                lblTransmissionValue.Text = _localCache.GetStringValue(ApplicationDataNames.TransmissionType, ad.TransmissionTypeId);
                lblListingTypeValue.Text = _localCache.GetStringValue(ApplicationDataNames.ListingType, ad.ListingTypeId);

                lblDescriptionDetail.Text = ad.Description.Replace(Environment.NewLine, "<br>");
                lblVehicleType.Text = ad.GetVehicleTypeString().ToUpper();
                lblPostDateValue.Text = DateTime.Now.ToString("D");

                PopulatePostUserInfo(ad);
            }
        }

        private void PopulatePostUserInfo(ForSaleAd post)
        {
            if (post.PostedByUserAccountId > 0)
            {
                // post by a registered user 
                pnlUnregisteredUser.Visible = false;

                IUserAccountService userAccountService = IocContainer.GetInstance<IUserAccountService>();
                UserAccountDto userDetails = userAccountService.GetUserAccountDetailsByUserId(post.PostedByUserAccountId);

                if (userDetails != null)
                {
                    lblRegisteredContact.Text = post.ContactName;
                    lblRegisteredPhone.Text = post.ContactPhone;
                    lblRegisteredEmail.Text = post.ContactEmail;
                    lblRegisteredCity.Text = post.CityName;

                    if (string.IsNullOrWhiteSpace(userDetails.UserProfilePhotoPath))
                    {
                        imgUserProfile.ImageUrl = GlobalSettings.DefaultProfilePhoto;
                    }
                    else
                    {
                        imgUserProfile.ImageUrl = userAccountService.GetProfilePhotoFileUrl(userDetails.UserProfilePhotoPath);
                    }

                    if (string.IsNullOrWhiteSpace(userDetails.UserLogoFilePath))
                    {
                        imgUserLogo.Visible = false;
                    }
                    else
                    {
                        imgUserLogo.ImageUrl = userAccountService.GetLogoFileUrl(userDetails.UserLogoFilePath);
                    }
                }
            }
            else
            {
                // post by anonymous user
                pnlRegisteredUser.Visible = false;

                lblAnonymousContact.Text = post.ContactName;
                lblAnonymousPhone.Text = post.ContactPhone;
                lblAnonymousEmail.Text = post.ContactEmail;
                lblAnonymousCity.Text = post.CityName;
            }
        }

        // try populate a for sale ad and save it to the session
        private bool TryMakeChangeToCurrentAd()
        {
            bool result = false;
            ForSaleAd change = _sessionService.GetSessionValue(SessionNames.NewForSaleAd) as ForSaleAd;

            // populate this new Ad instance
            change.ModelId = Convert.ToInt32(ddlModel.SelectedValue);
            change.ModelName = ddlModel.SelectedItem.Text;
            change.MakeId = Convert.ToInt32(ddlMake.SelectedItem.Value);
            change.YearMade = Convert.ToInt32(ddlYear.SelectedValue);
            change.YearMadeStr = ddlYear.SelectedItem.Text;
            change.MileAgeStr = Server.HtmlEncode(txtMileAgeValue.Text.Trim());
            change.PriceStr = Server.HtmlEncode(txtPrice.Text.Trim());

            change.VehicleConditionId = (int)(rbtUsed.Checked ? VehicleCondition.Used : VehicleCondition.New);
            change.TransmissionTypeId = (int) (rbtAutomatic.Checked ? TransmissionType.Automatic : TransmissionType.Manual);
            change.ListingTypeId = (int)(rbtOwner.Checked ? ListingTypes.Owner : ListingTypes.Dealer);

            change.Description = _validationService.SanitizeHtml(txtDescriptionDetail.Text.Trim());

            change.CityId = Convert.ToInt32(ddlCity.SelectedValue);
            change.CityName = ddlCity.SelectedItem.Text;
            change.ContactPhone = Server.HtmlEncode(txtPhoneNumber.Text.Trim());
            change.ContactEmail = Server.HtmlEncode(txtEmail.Text.Trim());
            change.ContactName = Server.HtmlEncode(tbxContactName.Text.Trim());

            IDictionary<PostForSaleFields, string> retDict = new Dictionary<PostForSaleFields, string>();

            if (!Validate(change, out retDict)) // validate the user inputs
            {
                // not valid, display error message
                DisplayInvalidPageMessage(retDict);
            }
            else
            {
                // ok to save to session
                _sessionService.SaveSessionValue(SessionNames.NewForSaleAd, change);
                result = true;
            }

            return result;
        }

        private void HideValidationLabels()
        {
            lblMileAgeValidation.Visible = false;
            lblPriceValidation.Visible = false;
            lblEmailValidation.Visible = false;
            lblDescriptionValidation.Visible = false;
        }

        public void DisplayInvalidPageMessage(IDictionary<PostForSaleFields, string> dict)
        {
            Dictionary<PostForSaleFields, Label> mapping = new Dictionary<PostForSaleFields, Label>()
            {
                { PostForSaleFields.Price, lblPriceValidation },
                { PostForSaleFields.MileAge, lblMileAgeValidation },
                { PostForSaleFields.ContactEmail, lblEmailValidation },
                { PostForSaleFields.Description, lblDescriptionValidation }
            };

            foreach (KeyValuePair<PostForSaleFields, string> item in dict)
            {
                Label lbl = mapping[item.Key];
                lbl.Text = item.Value;
                lbl.Visible = true;
            }
        }

        private bool Validate( ForSaleAd newAd, out IDictionary<PostForSaleFields, string> retDict )
        {
            return _validator.ValidateForSaleAd(newAd, out retDict);
        }

        private bool ValidateChanges( ForSaleAd ad, out IDictionary<PostForSaleFields, string> retDict )
        {
            return _validator.ValidateForSaleAd(ad, out retDict);
        }
        
        protected void btnEditPhotos_Click( object sender, EventArgs e )
        {
            // get the list of photos from session
            IList<UploadPhoto> listOfPhotos = GetUploadedPhotoListFromSession();

            int photoCount = listOfPhotos.Count;
            for (int i=1; i <= GlobalSettings.MaxNumOfUploadPhotos; ++i)
            {
                Image imgControl = programmaticPopup.FindControl(string.Format("img_{0}", i)) as Image;
                Label delSpan = programmaticPopup.FindControl(string.Format("imgBtn_{0}", i)) as Label;
                if (i <= photoCount)
                {
                    UploadPhoto photo = listOfPhotos[i-1];
                    imgControl.ImageUrl = _uploadPhotoService.GetThumbnailPhotoImageUrl(photo.PathOnServer);

                    delSpan.Visible = photoCount > 1;
                }
                else
                {
                    imgControl.ImageUrl = "../Images/space.gif";
                    delSpan.Visible = false;
                }
            }

            udpEditPhotos.Update();
            mpe1.Show();
        }

        protected void ddlMake_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            PopulateModelList( Convert.ToInt32(ddlMake.SelectedValue) );
        }
      
        // save change to the post
        protected void btnSaveEditChanges_Click(object sender, EventArgs e)
        {
            if (TryMakeChangeToCurrentAd())
            {
                // todo: display confirmation message
                DisplayAdDetails();

                this.mpeEditPost.Hide();
                udpPostInfo.Update();
                udpUserInfo.Update();
            }
        }

        protected void btnSaveEditPhotoClick(object sender, EventArgs e)
        {            
            DisplayPhotos();
            this.mpe1.Hide();
        }

        private void ClearSessionVariables()
        {
            _sessionService.ClearSessionVariable(SessionNames.ForSalePhotoList);
            _sessionService.ClearSessionVariable(SessionNames.NewForSaleAd);
        }

        // submit the new post to db!
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            object obj = _sessionService.GetSessionValue(SessionNames.NewForSaleAd);
            ForSaleAd adToSave = obj as ForSaleAd;

            if (obj != null)
            {
                // insert the new Ad and get the id
                string editKey;

                int newAdId = _adService.InsertNewForSaleAd(adToSave, out editKey);

                if (newAdId > 0)
                {
                    // save photo list
                    SavePhotoList(newAdId);
                    SaveNewPostInfoToSession(newAdId, editKey, adToSave.ContactEmail);

                    // redirect to confirm page
                    Response.Redirect(BuildConfirmationPageLink());
                }
                else
                {
                    // TODO: display error message
                }

                // clear session variables for newAd and photo
                ClearSessionVariables();
            }
        }

        private void SaveNewPostInfoToSession(int postId, string editKey, string email)
        {
            AdPostSucceedInfo info = new AdPostSucceedInfo { AdId = postId, EditKey = editKey, Email = email };
            _sessionService.SaveSessionValue(SessionNames.AdPostSucceedInfo, info);
        }

        private string BuildConfirmationPageLink()
        {
            return string.Format("~/PostForSale/PostForSaleConfirmation.aspx");
        }

        // save uploaded photos to database
        private void SavePhotoList(int newAdId)
        {
            IList<UploadPhoto> photoList = GetUploadedPhotoListFromSession();

            if (photoList.Any())
            {
                _uploadPhotoService.InsertPhotos(photoList, newAdId, AdType.ForSale);
            }
        }
    } 
}
